//
// Created by 17775 on 2024/11/13.
//

#include "Pointing_Stability.h"

void Pointing_Stability::stopPointingStability() {
    RayCi_PointingStability_Recording_stop(_iPointingStabilityDocId);
    if (getPointingStabilityDataThreadRunning.load(std::memory_order_acquire)) {
        stopPointingStabilityThread();
//        liveModePowerProfileOptions->close();
    }
}

void Pointing_Stability::stopPointingStabilityThread() {
    getPointingStabilityDataThreadRunning.store(false, std::memory_order_release);
    if (m_pointingStabilityThread.joinable()) {
        m_pointingStabilityThread.join();
    }
}

void Pointing_Stability::clearPointingStability() {
    RayCi_PointingStability_Recording_clear(_iPointingStabilityDocId);
}

void Pointing_Stability::setFrameSpan(int frames) {
    bool bFrameSpanAvailable = false;
    RayCi_PointingStability_Recording_Settings_isFrameSpanAvailable(_iPointingStabilityDocId, &bFrameSpanAvailable);
    if(bFrameSpanAvailable) {
        RayCi_PointingStability_Recording_Settings_setFrameSpan(_iPointingStabilityDocId, frames);
    }
}

void Pointing_Stability::setEveryFrame(bool bEveryFrame) {
    RayCi_PointingStability_Recording_Settings_setEveryFrame(_iPointingStabilityDocId, bEveryFrame);
}

void Pointing_Stability::setTimeSpan(double dTime) {
    bool bTimeSpanAvailable = false;
    RayCi_PointingStability_Recording_Settings_isTimeSpanAvailable(_iPointingStabilityDocId, &bTimeSpanAvailable);
    if(bTimeSpanAvailable) {
        if(dTime == 0) {
            setFreeRunning(true);
        } else {
            RayCi_PointingStability_Recording_Settings_setTimeSpan(_iPointingStabilityDocId, dTime);
        }
    }
}

void Pointing_Stability::setTimeStep(double dStep) {
    bool bTimeStepAvailable = false;
    RayCi_PointingStability_Recording_Settings_isTimeStepAvailable(_iPointingStabilityDocId, &bTimeStepAvailable);
    if(bTimeStepAvailable) {
        if(dStep == 0) {
            setEveryFrame(true);
        } else {
            RayCi_PointingStability_Recording_Settings_setTimeStep(_iPointingStabilityDocId, dStep);
        }
    }
}

void Pointing_Stability::setFreeRunning(bool freeRunning) {
    bool bFreeRunningAvailable = false;
    RayCi_PointingStability_Recording_Settings_isFreeRunningAvailable(_iPointingStabilityDocId, &bFreeRunningAvailable);
    if(bFreeRunningAvailable) {
        RayCi_PointingStability_Recording_Settings_setFreeRunning(_iPointingStabilityDocId, freeRunning);
    }
}

void Pointing_Stability::getData() {
    getPointingStabilityDataThreadRunning.store(true, std::memory_order_release);
    m_pointingStabilityThread = std::thread(&Pointing_Stability::getAllData, this);
}

void Pointing_Stability::getAllData() {
    int preLength = 0;
    PointingStabilityDataBatch batchData;
    while (getPointingStabilityDataThreadRunning.load(std::memory_order_acquire)) {
        int dataLength = 0;
        bool bRecording = false;
        RayCi_PointingStability_Recording_isRecording(_iPointingStabilityDocId, &bRecording);
        if(!bRecording) {
            getPointingStabilityDataThreadRunning.store(false, std::memory_order_release);
            emit pointingStabilityMeasurementOver();
        }
        RayCi_PointingStability_Chart_Data_getDataLength(_iPointingStabilityDocId, &dataLength);
        if (preLength != dataLength && dataLength > 0) {
            preLength = dataLength;
            batchData.vecXRelativeTimes.resize(dataLength);
            batchData.vecXValues.resize(dataLength);
            batchData.vecYRelativeTimes.resize(dataLength);
            batchData.vecYValues.resize(dataLength);
            RayCi_PointingStability_Chart_Data_getDataAsBinary(_iPointingStabilityDocId, 0, batchData.vecXRelativeTimes.data(), &dataLength, batchData.vecXValues.data(), &dataLength);
            RayCi_PointingStability_Chart_Data_getDataAsBinary(_iPointingStabilityDocId, 1, batchData.vecYRelativeTimes.data(), &dataLength, batchData.vecYValues.data(), &dataLength);
            emit getPointingStabilityData(batchData);
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

QString Pointing_Stability::getDataUnit(int nChartType) {
    char szUnit[20];
    int size = 20;
    RayCi_PointingStability_Chart_Data_getUnitA(_iPointingStabilityDocId, nChartType, &szUnit[0], &size);
    return QString::fromUtf8(szUnit);
}

double Pointing_Stability::getStatisticalResult(int nChartType, int nColumn) {
    double dResult = 0;
    RayCi_PointingStability_Analysis_Statistic_getResult(_iPointingStabilityDocId, nChartType, nColumn, &dResult);
    return dResult;
}

double Pointing_Stability::getAzimuthAngle() {
    double dAzimuthAngle = 0;
    RayCi_PointingStability_Analysis_Statistic_getAzimuthAngle(_iPointingStabilityDocId, &dAzimuthAngle);
    return dAzimuthAngle;
}

double Pointing_Stability::getMaxDistance() {
    double dMaxDistance = 0;
    RayCi_PointingStability_Analysis_Statistic_getMaxDistance(_iPointingStabilityDocId, &dMaxDistance);
    return dMaxDistance;
}

double Pointing_Stability::getWidthMajor() {
    double dWidthMajor = 0;
    RayCi_PointingStability_Analysis_Statistic_getWidthMajor(_iPointingStabilityDocId, &dWidthMajor);
    return dWidthMajor;
}

double Pointing_Stability::getWidthMinor() {
    double dWidthMinor = 0;
    RayCi_PointingStability_Analysis_Statistic_getWidthMinor(_iPointingStabilityDocId, &dWidthMinor);
    return dWidthMinor;
}

void Pointing_Stability::getCentroidXYView() {
//    bool bValid = false;
//    int size = 4200000;
//    unsigned  char nView_buffer[4200000];
//    RayCi_PointingStability_CentroidXY_View_isValid(_iPointingStabilityDocId, &bValid);
//    if(bValid) {
//        RayCi_PointingStability_CentroidXY_View_getViewA(_iPointingStabilityDocId, 2040, 2040, "", nView_buffer, &size);
//    }
}

void Pointing_Stability::exportReport() {
    RayCi_createDirectoryA("C:\\RayCi\\PointingStability");
    OPENFILENAMEA ofn;
    char szFile[260] = { 0 };
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = nullptr;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile) / sizeof(szFile[0]) - 1;
    ofn.lpstrFilter = "PDF Files(*.pdf)\0*.pdf*\0All Files(*.*)\0*.*\0\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrInitialDir = "C:\\RayCi\\PointingStability";
    ofn.lpstrTitle = "Save Report As";
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
    if (GetSaveFileNameA(&ofn) == TRUE) {
        const char* reportPathName = ofn.lpstrFile;
        std::string reportPathWithExtension = std::string(reportPathName) + ".pdf";
        RayCi_PointingStability_Report_exportA(_iPointingStabilityDocId, reportPathWithExtension.c_str());
        ShellExecuteA(nullptr, "open", reportPathWithExtension.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
    } else {
        MessageBoxA(nullptr, "Export was cancelled.", "Info", MB_OK | MB_ICONINFORMATION);
    }
}

void Pointing_Stability::closePointingStability(bool bWaitWhileClosing) {
    RayCi_PointingStability_close(_iPointingStabilityDocId, bWaitWhileClosing);
}

void Pointing_Stability::closeAllPointingStability(bool bWaitWhileClosing) {
    RayCi_PointingStability_closeAll(bWaitWhileClosing);
}

Pointing_Stability::~Pointing_Stability() {
    getPointingStabilityDataThreadRunning.store(false, std::memory_order_release);
    if(m_pointingStabilityThread.joinable()) {
        m_pointingStabilityThread.join();
    }
}